﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 转发程序
{
    /// <summary>
    /// 通讯控制
    /// </summary>
    public class CommunicationControl窜改数据 : 通讯控制
    {
        //192.168.58.80|8405^192.168.58.75|8405
        public string 转发目标字符串 = System.Configuration.ConfigurationManager.AppSettings["转发目标"];

        /// <summary>
        /// 单向，双向
        /// </summary>
        public string 双向通讯 = System.Configuration.ConfigurationManager.AppSettings["双向通讯"];




        /// <summary>
        /// 初始化通讯控制
        /// </summary>
        /// <param name="_监听服务"></param>
        public CommunicationControl窜改数据(监听服务 _监听服务)
        {
            监听服务 = _监听服务;

        }

        #region 通讯控制 成员
        private 监听服务 _监听服务 = null;
        public 监听服务 监听服务
        {
            get
            {
                return _监听服务;
            }
            set
            {
                _监听服务 = value;
                value.OnAcceptSocket += new EventHandler<ControlCenter.通讯.TcpServerEventArgs>(value_OnAcceptSocket);
                value.OnClientDisconnected += new EventHandler<ControlCenter.通讯.TcpServerEventArgs>(value_OnClientDisconnected);
                value.OnReceiveData += new EventHandler<ControlCenter.通讯.TcpServerEventArgs>(value_OnReceiveData);
            }
        }

        /// <summary>
        /// 接收到数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void value_OnReceiveData(object sender, ControlCenter.通讯.TcpServerEventArgs e)
        {
            lock (联接对像集合)
            {
                if (联接对像集合.ContainsKey(e.ServerSocket.UserData))
                {
                    //得到目标联接对像
                    联接对像 对像 = 联接对像集合[e.ServerSocket.UserData];

                    foreach (var item in 对像.转发目标集合.Values)
                    {
                        System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WaitCallback), new { item = item, socket = e });
                    }

                }
            }
        }
        /// <summary>
        /// 客户端中断联接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void value_OnClientDisconnected(object sender, ControlCenter.通讯.TcpServerEventArgs e)
        {
            //这里长时间运行后会出现一个null异常的情况
            if (e.ServerSocket.UserData != null)
            {
                //收到数据对目标socket进行发送, 如果目标Socket联接没有联上则先联接再发送
                lock (联接对像集合)
                {
                    if (联接对像集合.ContainsKey(e.ServerSocket.UserData))
                    {
                        //全部关闭
                        联接对像集合[e.ServerSocket.UserData].Close();
                        //从队列字典中移除
                        联接对像集合.Remove(e.ServerSocket.UserData);
                    }
                }
            }
        }

        /// <summary>
        /// 新加的通讯联接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void value_OnAcceptSocket(object sender, ControlCenter.通讯.TcpServerEventArgs e)
        {
            ///转发目标集合
            List<转发目标> Tararr = new List<转发目标>();

            //192.168.58.80|8405^192.168.58.75|8405
            if (转发目标字符串.Length > 0)
            {
                if (转发目标字符串.Split('^').Length > 0)
                {
                    //加上东东
                    e.ServerSocket.UserState = Num++;


                    //将配置转换成实例对像
                    foreach (string str in 转发目标字符串.Split('^'))
                    {
                        //得到当前 目标的数组  
                        string[] strarr = str.Split('|');

                        //创建一个TCP对像
                        var socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);

                        //转换目标
                        Tararr.Add(new TransmitTarget()
                        {
                            接收器通讯Socket = e.ServerSocket,
                            目标IP = strarr[0],
                            目标端口 = int.Parse(strarr[1]),
                            转换器 = new ConvertBuffer(),
                            目标机通讯Socket = new ControlCenter.通讯.TcpServerSocket(socket)
                            {
                            }

                        });



                    }
                }
            }

            联接对像 conn = new 联接对像(e.ServerSocket, Tararr);
            lock (联接对像集合)
            {
                //如果不包含这个Key才添加
                if (!联接对像集合.ContainsKey(e.ServerSocket.Socket.RemoteEndPoint.ToString()))
                {
                    联接对像集合.Add(e.ServerSocket.Socket.RemoteEndPoint.ToString(), conn);
                }
                //如果已经存在这个key 则替换
                else
                {
                    联接对像集合[e.ServerSocket.Socket.RemoteEndPoint.ToString()] = conn;
                }
            }




        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="state"></param>
        void WaitCallback(object state)
        {
            dynamic oject = state;

            转发目标 item = (转发目标)oject.item;
            ControlCenter.通讯.TcpServerEventArgs e = (ControlCenter.通讯.TcpServerEventArgs)oject.socket;

            if (!item.目标机通讯Socket.Socket.Connected)
            {
                try
                {
                    item.目标机通讯Socket.Socket.Connect(item.目标IP, item.目标端口);

                    item.目标机通讯Socket.Socket.Send(
                                    item.转换器.Convert(
                                       ReplaceBuffer(e.ServerSocket.Buffer.Take(e.DataSize).ToArray(), (int)e.ServerSocket.UserState)
                                    )
                                    );
                    //配置是双向才启动接收发送数据功能e
                    if (双向通讯 == "双向")
                    {
                        item.启动转发目标接收数据功能();
                    }
                }
                ///如果联接不上则使用异步联接
                catch (System.Net.Sockets.SocketException ex)
                {

                }
                catch (ObjectDisposedException oex)
                { }
                //联接已经断开
                catch (System.InvalidOperationException)
                {
                    //没有联接上
                    if (!item.目标机通讯Socket.Socket.Connected)
                    {
                        try
                        {
                            //关闭联接
                            item.目标机通讯Socket.Socket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
                            item.目标机通讯Socket.Socket.Close();
                            item.目标机通讯Socket.Socket.Dispose();
                        }
                        catch
                        { }
                    }

                    //创建一个新的Socekt联接对像
                    System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
                    item.目标机通讯Socket = new ControlCenter.通讯.TcpServerSocket(socket);

                    try
                    {
                        item.目标机通讯Socket.Socket.Connect(item.目标IP, item.目标端口);
                        item.目标机通讯Socket.Socket.Send(
                                        item.转换器.Convert(
                                       ReplaceBuffer(e.ServerSocket.Buffer.Take(e.DataSize).ToArray(), (int)e.ServerSocket.UserState)
                                    )
                                        );
                        //配置是双向才启动接收发送数据功能
                        if (双向通讯 == "双向")
                        {
                            item.启动转发目标接收数据功能();
                        }
                    }
                    ///目标主机拒绝 异常不做处理
                    catch (System.Net.Sockets.SocketException ex)
                    {
                        try
                        {
                            //关闭联接
                            socket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
                            socket.Close();
                            socket.Dispose();
                        }
                        catch
                        {

                        }
                    }
                    catch (ObjectDisposedException oex)
                    { }
                }

            }
            else
            {
                if (item.目标机通讯Socket.Socket.Connected)
                {
                    try
                    {
                        item.目标机通讯Socket.Socket.Send(
                                    item.转换器.Convert(
                                       ReplaceBuffer(e.ServerSocket.Buffer.Take(e.DataSize).ToArray(), (int)e.ServerSocket.UserState)
                                    )
                                    );
                    }
                    catch { }
                }
            }
        }

        /// <summary>
        /// 联接对像集合
        /// </summary>
        private Dictionary<string, 联接对像> _联接对像集合 = new Dictionary<string, 联接对像>();
        /// <summary>
        /// 联接对像集合
        /// </summary>
        public Dictionary<string, 联接对像> 联接对像集合
        {
            get { return _联接对像集合; }

        }
        /// <summary>
        /// 检查状态 如果没有联上则断开
        /// </summary>
        public void CheckConnection()
        {
            foreach (var item in 联接对像集合.ToList())
            {
                if (!item.Value.接入联接.Socket.Connected)
                {
                    item.Value.Close();
                }

            }
        }

        #endregion

        #region 窜改数据


        public static int Num = 1;
        string strBus = "47-50-52-53-01-02-03-04-05-06-07-08";

        /// <summary>
        /// 替换指定数据
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public byte[] ReplaceBuffer(byte[] buffer, int num)
        {
            if (Num > 20000)
            {
                Num = 1;
            }
            //转换成16进制码
            string hexStr = BitConverter.ToString(buffer);
            int index = hexStr.IndexOf("47-50-52-53");
            string replaceStr = "47-50-52-53" + "-" + BitConverter.ToString(System.Text.Encoding.UTF8.GetBytes("01S" + num.ToString("d5")));
            //包括GPRS 包头
            if (index != -1)
            {
                //车辆内部编码
                string busCode = hexStr.Substring(index, strBus.Length);
                //替换数据
                buffer = HexStringToBytes(hexStr.Replace(busCode, replaceStr).Split('-')) as byte[];
            }
            return buffer;
        }

        /// <summary>
        /// 转换 单字节的 16 进制
        /// </summary>
        /// <param name="HexStr">16进制的字符串</param>
        /// <returns>返回 字节</returns>
        protected virtual byte HexStringToByte(string HexStr)
        {
            return byte.Parse(HexStr, System.Globalization.NumberStyles.HexNumber, null);
        }
        /// <summary>
        /// 传入一个十六进帛的数据组如 F1,F2,AA 这样的数组
        /// </summary>
        /// <param name="HexStrs">十六进制一个字节字符串一个行的数组</param>
        /// <returns>十六进制字符串所对应的字节数组</returns>
        protected virtual IEnumerable<byte> HexStringToBytes(string[] HexStrs)
        {
            var bytrarr = (from p in HexStrs.Where(x => x != "")
                           select HexStringToByte(p)).AsParallel().ToArray();
            return bytrarr;
        }
        #endregion
    }
}
